package com.linkhub.oms.component.redis.config;

import com.linkhub.oms.component.redis.config.cache.LinkhubRedisCacheWriter;
import com.linkhub.oms.component.redis.config.serializer.RedisJsonSerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import javax.annotation.Resource;
import java.time.Duration;

/**
 * @Description: LinkhubRedisConfig
 * @Author: echo
 * @Date: 2024/3/3 10:29
 * @Version: 1.0
 */
@Slf4j
@Configuration
@EnableCaching
public class LinkhubRedisConfig extends CachingConfigurerSupport {

    /**
     * 注入 RedisConnectionFactory
     */
    @Resource
    private RedisConnectionFactory redisConnectionFactory;

    /**
     * 实例化 RedisTemplate 对象
     *
     * @return RedisTemplate
     */
    @Bean
    @Primary
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        initDomainRedisTemplate(redisTemplate);
        return redisTemplate;
    }

    /**
     * 设置数据存入 redis 的序列化方式
     *
     * @param redisTemplate redisTemplate
     */
    private void initDomainRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        redisTemplate.setHashValueSerializer(RedisJsonSerializer.JACKSON_JSON_REDIS_SERIALIZER);
        redisTemplate.setValueSerializer(stringRedisSerializer);
        redisTemplate.setConnectionFactory(redisConnectionFactory);
    }

    @Bean
    @Override
    public CacheManager cacheManager() {
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                // 缓存前缀转换规则（默认会加两个冒号，方法：org.springframework.data.redis.cache.CacheKeyPrefix.simple），这里不作转换
                .computePrefixWith(cacheName -> cacheName)
                // 指定值的序列化方式
                .serializeValuesWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(RedisJsonSerializer.JACKSON_JSON_REDIS_SERIALIZER))
                // 设置缓存的过期时间
                .entryTtl(Duration.ofDays(1));

        return RedisCacheManager.builder(new LinkhubRedisCacheWriter(redisConnectionFactory))
                .cacheDefaults(redisCacheConfiguration)
                .build();
    }

    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return (target, method, params) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append(":");
            sb.append(method.getName());
            for (Object obj : params) {
                sb.append(":").append(obj.toString());
            }
            return sb.toString();
        };
    }

}
